/*
 * LDIR
 *
 * LDIR, a GPS cartography application built for Let's Do It Romania eco
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 *
 * http://generasoftware.com/
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#ifndef __CLIENTENGINE_H__
#define __CLIENTENGINE_H__

#include <coecntrl.h>
#include <http\mhttpdatasupplier.h>
#include <http\mhttptransactioncallback.h>
#include <http\mhttpauthenticationcallback.h>
#include <es_sock.h>
#include "Logger.h"

/*
 * Forward declarations
 */
class RHTTPSession;
class RHTTPTransaction;
class CConnectionOpener;
class CHttpFilter;

/*
 * MClientObserver
 * CClientEngine passes events and responses body data with this interface.
 * An instance of this class must be provided for construction of CClientEngine.
 */
class MHttpClientObserver
    {
public:
    virtual void ClientEventL(const TInt aEvent) = 0;
    virtual void ClientBodyReceivedL(const TDesC8& aBodyData) = 0;
    virtual void ClientErrorL(const TInt aError) = 0;
    virtual void CancelledL() = 0;
    };

/**
 * A mixin class for notifying about IAP connection.
 */
class MConnectionObserver
    {
public:

    /**
     * Called when opening a IAP connection has finished
     */
    virtual void ConnectionCreatedL(const TInt& aError) = 0;
    };

/*
 * Provides simple interface to HTTP Client API.
 */
class CHttpClient : public CBase,
        public MHTTPTransactionCallback,
        public MHTTPAuthenticationCallback,
        public MConnectionObserver
    {
public:

    enum TClientEvents
        {
        EFailedToConnect = KErrCouldNotConnect,
        EConnectionTimedOut = KErrTimedOut,
        EOperationCancelled = KErrCancel,
        ETransactionFailed = -2,
        ENoConnection = -1,
        EConnecting,
        EConnectionSucceded,
        ETransactionSucceded,
        ETransactionComplete,
        ETransactionGotResponseHeaders,
        ETransactionGotResponseBodyData,
        ETransactionBodyReceived,
        ETransactionCancelled,
        ETransactionUnrecognizedEvent
        };
    ~CHttpClient();

    static CHttpClient* NewL(MHttpClientObserver& iObserver);
    static CHttpClient* NewLC(MHttpClientObserver& iObserver);

    void ConnectL();
    void IssueHTTPPostL(const TDesC8& aUri, const TDesC8& aContentType,
            const TDesC8& aOAuth, MHTTPDataSupplier* aSupplier);
    void IssueHTTPGetL(const TDesC8& aUri, const TDesC8& aContentType,
            const TDesC8& aOAuth, MHTTPDataSupplier* aSupplier);
    void IssueHTTPDeleteL(const TDesC8& aUri, const TDesC8& aContentType,
            const TDesC8& aOAuth, MHTTPDataSupplier* aSupplier);
    void CancelTransaction();
    inline TBool IsRunning()
        {
        return iRunning;
        }

    void ResetData();

private:

    void ConstructL();
    CHttpClient(MHttpClientObserver& iObserver);
    void SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField,
            const TDesC8& aHdrValue);
    void SetHeaderL(RHTTPHeaders aHeaders, const TDesC8& aFielName,
            const TDesC8& aFieldValue);
    void RemoveValidationFilter();

private:
    // MHTTPSessionEventCallback

    void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
    TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction,
            const THTTPEvent& aEvent);
    // From MConnectionObserver
    void ConnectionCreatedL(const TInt& aError);

private:
    // MHTTPAuthenticationCallback

    TBool GetCredentialsL(const TUriC8& aURI, RString aRealm,
            RStringF aAuthenticationType, RString& aUsername,
            RString& aPassword);

private:
    // declare members
    RSocketServ iSockServ;
    RConnection iConnection;
    RHTTPSession iHttpSession;
    RHTTPTransaction iTransaction;
    MHttpClientObserver& iObserver; // Used for passing body data and
    // events to UI.
    CConnectionOpener* iConnOpener;
    TBool iRunning; // ETrue, if transaction running
    TBool iOpeningConnection;
    CHttpFilter* iCustomValidationFilter;
    };

inline void Panic(TInt aPanicCode)
    {
    _LIT(KApplicationName, "Server");
    LOG(EVerbosityCore, _L("!!!PANIC!!! - panic code = %d"), aPanicCode);
    User::Panic(KApplicationName, aPanicCode);
    }

inline void PanicIfError(TInt aPanicCode)
    {
    if (aPanicCode != KErrNone)
        {
        Panic(aPanicCode);
        }
    }

#endif // __CLIENTENGINE_H__
